﻿using System;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Reflection;
using System.Threading;

namespace WebServer.Modules
{
	/// <summary>
	/// Handles all firewalled IP Addresses
	/// </summary>
	[CoreModule("Firewall", typeof(Firewall), CoreModulePriority.High)]
	public static class Firewall
	{
		private static List<IPAddress> _Addresses = new List<IPAddress>();
		/// <summary>
		/// Stores all firewalled IP Addresses
		/// </summary>
		public static List<IPAddress> Addresses { get { return _Addresses; } }

		/// <summary>
		/// Initializes the Firewall
		/// </summary>
		private static void Start()
		{
			Events.CoreInitialized += new CoreInitializedEventHandler(Events_CoreInitialized);
			Events.CoreClosed += new CoreClosedEventHandler(Events_CoreClosed);
		}

		private static void Events_CoreInitialized()
		{
			Load();
		}

		private static void Events_CoreClosed()
		{
			Save();
		}

		/// <summary>
		/// Registers an IP Address with the Firewall
		/// </summary>
		/// <param name="address">The byte array value of the IP address</param>
		public static void Add(byte[] address)
		{
			IPAddress ip = new IPAddress(address);

			if (!_Addresses.Contains(ip))
			{ _Addresses.Add(ip); }
		}

		public static bool Contains(byte[] address)
		{
			IPAddress ip = new IPAddress(address);

			return Contains(ip);
		}

		public static bool Contains(IPAddress address)
		{
			return _Addresses.Contains(address);
		}

		/// <summary>
		/// Registers an IP Address with the Firewall
		/// </summary>
		/// <param name="address">The IP address</param>
		public static void Add(IPAddress address)
		{
			if (!_Addresses.Contains(address))
			{ _Addresses.Add(address); }
		}

		private static void Save()
		{
			FileInfo info = IOUtility.EnsureFile(Core.BaseDirectory + "\\" + Config.SystemName + "\\Cache\\firewall.cache", true);

			using (StreamWriter writer = new StreamWriter(info.Open(FileMode.Truncate)))
			{
				foreach (IPAddress ip in _Addresses)
				{
					byte[] bytes = ip.GetAddressBytes();

					writer.WriteLine("{0}.{1}.{2}.{3}", bytes[0], bytes[1], bytes[2], bytes[3]);
				}

				writer.Close();
			}
		}

		private static void Load()
		{
			FileInfo info = IOUtility.EnsureFile(Core.BaseDirectory + "\\" + Config.SystemName + "\\Cache\\firewall.cache", false);

			using (StreamReader reader = new StreamReader(info.OpenRead()))
			{
				string[] lines = File.ReadAllLines(info.FullName, Encoding.Default);

				foreach (string line in lines)
				{
					if (String.IsNullOrEmpty(line))
						continue;

					string[] split = line.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);

					if (split.Length != 4)
						continue;

					byte[] address = new byte[4] 
					{
						Byte.Parse(split[0]), 
						Byte.Parse(split[1]),
						Byte.Parse(split[2]), 
						Byte.Parse(split[3])
					};

					Add(address);
				}

				reader.Close();
			}
		}
	}
}
